package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.feign.article.IArticleClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: JW
 * @Description: TODO
 * @DateTime: 2022-02-14 22:23
 **/
@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {


    @Autowired
    private WmNewsService wmNewsService;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private GreenImageScan greenImageScan;

    @Resource
    private IArticleClient iArticleClient;

    @Autowired
    private WmChannelService wmChannelService;

    @Autowired
    private WmUserService wmUserService;

    @Autowired
    private WmSensitiveService wmSensitiveService;

    @Autowired
    private Tess4jClient tess4jClient;

    /**
     * @param id 文章id
     * @Author: JW
     * @Description: TODO 文章审核
     * @Date: 22:23 2022-02-14
     * @Param: [id]
     * @return: void
     */
    @Override
    @Async
    public void autoScanWmNews(Integer id) {

        //参数校验
        if (id == null){
            return;
        }

        //根据id查询文章
        WmNews wmNews = wmNewsService.getById(id);

        if (wmNews == null){
            throw  new RuntimeException("文章不存在");
        }

        //当文章处于提交状态时开始审核
        if(wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){


            //所有图片
            List<String> imagesString = new ArrayList<>();

            //审核所有文字
            //标题
            StringBuilder content = new StringBuilder(wmNews.getTitle());
            content.append(wmNews.getLabels());

            //拿出内容
            List<Map> contentMap = JSON.parseArray(wmNews.getContent(), Map.class);

            //取出内容中文字 并拼接到内容文字中
            for (Map map : contentMap) {
                //添加文字
                if ("text".equals(map.get("type"))){
                    content.append(map.get("value"));
                }
                //添加图片
                if ("image".equals(map.get("type"))){
                    imagesString.add(map.get("value").toString());
                }
            }

            //进行自定义词语审核
            if (!checkText(wmNews,content.toString())){
                return;
            }


            //进行阿里云文本审核
            //审核不通过，直接返回
            if (!checkTextAliyun(wmNews, content.toString())){
                return;
            }

            //审核图片
            //添加封面图片
            String[] split = wmNews.getImages().split(",");
            List<String> images = Arrays.asList(split);

            imagesString.addAll(images);

            //存在图片时审核
            if (imagesString.size() > 0 && !"".equals(imagesString.get(0))){

                //ORC审核
                //字节图片集合
                ArrayList<byte[]> imageBytes = new ArrayList<>();

                for (String image : imagesString) {

                    byte[] imageByte = fileStorageService.downLoadFile(image);

                    imageBytes.add(imageByte);

                    try {
                        //从byte[]转换为butteredImage
                        ByteArrayInputStream in = new ByteArrayInputStream(imageByte);
                        BufferedImage imageFile = ImageIO.read(in);
                        //得到文字识别的内容
                        String text = tess4jClient.doOCR(imageFile);

                        if (text != null){
                            //进行自定义审核和阿里云审核
                            if (!checkText(wmNews,text) || !checkTextAliyun(wmNews, text)){
                                return;
                            }
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    //进行阿里云图片审核
                    if (!checkImagesAliyun(wmNews, imageBytes)){
                        return;
                    }
                }
            }

            //进行远程调用保存文章到用户端
            Long articleId = saveNewToAPP(wmNews);

            //回填app端文章id
            wmNews.setArticleId(articleId);

            //再次修改文章
            updateWmNews(wmNews,(short) 9,"审核成功");

        }

    }

    /**
     * @Author: JW
     * @Description:  TODO 自定义词汇审核 数据库中词汇
     * @Date: 18:22 2022-02-16
     * @Param: [wmNews, content]
     * @return: boolean
    **/
    private boolean checkText(WmNews wmNews, String content) {

        boolean flag = true;

        //拿到所有的敏感词汇
        List<WmSensitive> sensitiveList = wmSensitiveService.list();
        List<String> sensitives = sensitiveList.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());

        //用工具类对敏感词汇进行初始化
        SensitiveWordUtil.initMap(sensitives);

        Map<String, Integer> sensitiveMap = SensitiveWordUtil.matchWords(content);

        if (sensitiveMap.size() > 0){
            flag = false;
            //对文章进行修改
            updateWmNews(wmNews,(short) 2,"当前文章中存在违规内容"+sensitiveMap);
        }

        return flag;
    }

    /**
     * @Author: JW
     * @Description:  TODO 远程调用保存文章到app端
     * @Date: 17:07 2022-02-16
     * @Param: [wmNews]
     * @return: java.lang.Long 返回拿到文章id回填到文章中
    **/
    private Long saveNewToAPP(WmNews wmNews) {
        ArticleDto dto = new ArticleDto();
        //属性的拷贝
        BeanUtils.copyProperties(wmNews,dto);
        //文章的布局
        dto.setLayout(wmNews.getType());
        //频道
        WmChannel wmChannel = wmChannelService.getById(wmNews.getChannelId());
        if(wmChannel != null){
            dto.setChannelName(wmChannel.getName());
        }

        //作者
        dto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserService.getById(wmNews.getUserId());
        if(wmUser != null){
            dto.setAuthorName(wmUser.getName());
        }

        //设置文章id
        if(wmNews.getArticleId() != null){
            dto.setId(wmNews.getArticleId());
        }
        dto.setCreatedTime(new Date());

        ResponseResult responseResult = iArticleClient.saveArticle(dto);

        if (responseResult.getCode() != 200){
            throw new RuntimeException("app端保存文章失败");
        }

        String id = responseResult.getData().toString();

        return Long.valueOf(id);

    }

    /**
     * @Author: JW
     * @Description:  TODO 进行阿里云图片审核
     * @Date: 16:55 2022-02-16
     * @Param: [wmNews, imageBytes]
     * @return: java.lang.Boolean
    **/
    private Boolean checkImagesAliyun(WmNews wmNews, ArrayList<byte[]> imageBytes) {

        Boolean flag = true;

        try {
            Map map = greenImageScan.imageScan(imageBytes);

            if (map != null){
                //审核失败
                if("block".equals(map.get("suggestion"))){
                    flag = false;
                    updateWmNews(wmNews, (short) 2, "当前文章中存在违规图片");
                }

                //不确定信息  需要人工审核
                if("review".equals(map.get("suggestion"))){
                    flag = false;
                    updateWmNews(wmNews, (short) 3, "当前文章中存在不确定元素");
                }
            }
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
        }

        return flag;
    }

    /**
     * @Author: JW
     * @Description:  TODO 使用阿里云进行文本审核
     * @Date: 16:54 2022-02-16
     * @Param: [wmNews, content]
     * @return: java.lang.Boolean
    **/
    private Boolean checkTextAliyun(WmNews wmNews, String content) {

        Boolean flag = true;

        try {
            Map map = greenTextScan.greeTextScan(content);

            if (map != null){
                //审核失败
                if("block".equals(map.get("suggestion"))){
                    flag = false;
                    updateWmNews(wmNews, (short) 2, "当前文章中存在违规内容");
                }

                //不确定信息  需要人工审核
                if("review".equals(map.get("suggestion"))){
                    flag = false;
                    updateWmNews(wmNews, (short) 3, "当前文章中存在不确定内容");
                }
            }

        } catch (Exception e) {
            flag =  false;
            e.printStackTrace();
        }

        return flag;
    }

    /**
     * @Author: JW
     * @Description:  TODO 修改文章
     * @Date: 16:29 2022-02-16
     * @Param: [wmNews, status, reason] 文章 状态 决绝理由
     * @return: void
    **/
    private void updateWmNews(WmNews wmNews, short status, String reason) {

        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsService.updateById(wmNews);
    }
}
